package com.gzsxy.esjy.common.base.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xiaolong
 * @version 1.0
 * @description: 文件操作类
 * @date 2021/9/30 15:02
 */
public class FileUtils {

    private final static Map<String, Object> cahe = new HashMap<>();

    private final static List<File> list = new ArrayList<>();


    /**
     * @param file json文件
     * @return jsonObject   实体对象
     * @description: 刷新文件
     */
    public static void flushJson(File file, Object jsonObject) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(JSON.toJSONBytes(jsonObject));
            //存入map内存当中，下次查询文件直接查内存，不用进行IO操作
            cahe.put(file.getPath(), jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(fos);
        }
    }


    /**
     * @param file  json文件
     * @param clazz 返回实体封装对象
     * @return
     * @description: 获取本地json
     */
    public static <T> T getLocalJson(File file, Class<T> clazz) {
        T obj = (T) cahe.get(file.getPath());
        //如果不为空说明，之前刷新文件时就存在内存map当中，直接返回对象；
        if (obj != null) {
            return obj;
        }
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            //转为object对象
            obj = JSON.parseObject(in, clazz);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(in);
        }
        return obj;
    }

    /**
     *###################################################################################################
     *  处理读取json文件外部配置文件
     *###################################################################################################
     */


    /**
     * @description: 获取list列表json
     * @param path  文件路径
     * @param clazz 返回实体封装对象
     * @return  返回列表对象
     */
    public static <T> List<T> getlistInJson(String path,Class<T> clazz){
        return getlistInJson(new File(path),clazz);
    }

    /**
     * @description: 获取list列表json
     * @param file  json文件
     * @param clazz 返回实体封装对象
     * @return  返回列表对象
     */
    public static <T> List<T> getlistInJson(File file, Class<T> clazz) {
        if (file.exists() && !file.getName().toLowerCase().endsWith("json")){
            return JSON.parseArray(readFile(file),clazz);
        }
        return null;
    }


    /**
     * @description: 读取json数组 返回实体对象
     * @param file json文件
     * @param clazz 实体类对象
     * @return  实体类对象
     */
    public static <T> T getObjectInJsonFile(File file,Class<T> clazz){
        //文件必须为json后缀
        if (file.exists() && file.getName().toLowerCase().endsWith("json")){
            String data = readFile(file);
            return JSON.parseObject(data,clazz);
        }
        return null;
    }

    /**
     * @description: 读取json数组 返回实体对象 （推荐使用）
     * @param in 文件输入流
     * @param clazz 实体类对象
     * @return 实体类对象
     */
    public static <T> T getObjectInJsonFile(InputStream in,Class<T> clazz){
        try {
            byte[] bytes = getStreamBytes(in);
            if (bytes != null){
                return JSON.parseObject(new String(bytes,"utf-8"),clazz);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @description: 读取json数组 返回实体对象
     * @param path 文件路径
     * @param clazz 实体类对象
     * @return 实体类对象
     */
    public static <T> T getObjectInJsonFile(String path,Class<T> clazz){
        return getObjectInJsonFile(new File(path),clazz);
    }


    /**
     * @description: 通过文件file读取String字符串(尽量不要用，jar内部获取的file是加jar！目录，找不到文件目录)
     * @param file json文件
     * @return json字符串
     */
    public static String readFile(File file){
        FileInputStream in =null;
        ByteArrayOutputStream baos =null;
        BufferedInputStream bis = null;
        try {
            in = new FileInputStream(file);
            bis = new BufferedInputStream(in);
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len =bis.read(buffer)) != -1){
                baos.write(buffer,0,len);
            }
            return baos.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(baos, bis, in);
        }
        return null;
    }

    /**
     * @description: 通过文件流InputStream读取String字符串(推荐使用)
     * @param in 输入流
     * @return json字符串
     */
    public static String readFile(InputStream in){
        ByteArrayOutputStream baos =null;
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(in);
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len =bis.read(buffer)) != -1){
                baos.write(buffer,0,len);
            }
            return baos.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(baos, bis, in);
        }
        return null;
    }

    /**
     * @description: 通过输入流读取byte字节数组
     * @param is 输入流
     * @return byte字节数组
     */
    public static byte[] getStreamBytes(InputStream is) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            baos.write(buffer,0,len);
        }
        byte[] b = baos.toByteArray();
        is.close();;
        baos.close();
        return b;
    }






    /**
     * @param dir  目录
     * @param name 文件名
     * @return
     * @description: 保存文件
     */
    public static String createFileOfByte(byte[] bytes, String dir, String name) throws Exception {
        FileOutputStream fos = null;
        //判断目录是否存在
        if (mkdir(dir)) {
            String fullPath = dir + name;
            try {
                fos = new FileOutputStream(fullPath);
                fos.write(bytes);
                fos.flush();
                return fullPath;
            } finally {
                close(fos);
            }
        }
        return null;
    }


    /**
     * @param bytes    数据字节
     * @param fullPath 文件路径
     * @return
     * @description: 保存文件
     */
    public static String createFileOfByte(byte[] bytes, String fullPath) throws Exception {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(fullPath);
            fos.write(bytes);
            //强制写入
            fos.flush();
            return fullPath;
        } finally {
            close(fos);
        }
    }


    /**
     * @param
     * @return
     * @description: 文件复制
     */
    public static void copyfile(File src, File desc) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(desc);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(fos, fis);
        }
    }


    /**
     * @param dir 文件目录
     * @return
     * @description: 创建目录
     */
    public static boolean mkdir(String dir) {
        File file = new File(dir);
        if (!file.exists()) {
            return file.mkdir();
        }
        return true;
    }


    /**
     * @param path 文件路径
     * @return
     * @description: 删除文件
     */
    public static boolean deleteFile(String path) {
        File file = new File(path);
        //获取父目录
        File parentFile = file.getParentFile();
        file.delete();
        //如果父目录下没有文件，删除目录
        if (parentFile.list().length == 0) {
            return deleteFile(parentFile.getPath());
        }
        return true;
    }


    /**
     * @param dir
     * @return
     * @description: 递归删除目录下的所有文件及子目录下所有的文件
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] list = dir.list();
            //递归删除目录中的子目录下
            for (int i = 0; i < list.length; i++) {
                boolean success = deleteDir(new File(dir, list[i]));
                if (!success) {
                    return false;
                }
            }
        }
        System.out.println("删除文件：" + dir.getPath());
        return dir.delete();
    }


    /**
     * @param path 目录
     * @return List<File> 所有的文件
     * @description: 获取目录下所有的文件
     */
    public static List<File> getAllFile(String path) {
        File file = new File(path);
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) {
                getAllFile(file1.getPath());
            }
            list.add(file1);
        }
        return list;
    }


    /**
     * @description: 文件下载
     * @param path 文件路径
     * @param showFileName 文件显示名称（带后缀）
     * @return
     */
    public void downLoad(String path, String showFileName, HttpServletResponse response)  {
        InputStream inputStream = null;
        ServletOutputStream outputStream = null;
        try {
            //清空输出流
            response.reset();
            response.setHeader("content-disposition","attachment; filename="+new String(showFileName.getBytes("GB2312"),"ISO8859-1"));
            response.setContentType("application/msexcel");
            outputStream = response.getOutputStream();
            PathMatchingResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();
            Resource resource = resourceLoader.getResource(path);
            if (resource == null){
                response.setStatus(HttpStatus.SC_NOT_FOUND);
                return;
            }
            inputStream = resource.getInputStream();
            byte[] bytes = new byte[1024];
            int length = -1;
            while ((length =inputStream.read(bytes)) >0){
                outputStream.write(bytes,0,length);
            }
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        } finally {
            close(outputStream, inputStream);
        }
    }


    /**
     * @description: 导入word文档
     * @param
     * @return
     */
    public static void exportWord(String data,String fileName,HttpServletResponse response){
        try {
            IOUtils.toInputStream(data,"utf-8");
            OutputStream out = response.getOutputStream();
            //设置扩展头 当content-Type的类型要下载的类型时，这个信息头回告诉浏览器这个文件何类型
            String contentType = new MimetypesFileTypeMap().getContentType(fileName);
            response.setContentType(contentType);
            //设置编码
            fileName = URLEncoder.encode(fileName, "UTF-8");
//            response.setHeader(HttpHeaders.CONTEN);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    /**
     * @param args
     * @return
     * @description: 关闭流
     */
    public static void close(Closeable... args) {
        for (Closeable closeable : args) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * @description: object转json字符串
     * @param
     * @return
     */
    public static String obiectToJson(Object object) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            //将传入的对象序列化为json，返回给调用者
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            return null;
        }
    }



    //测试
    public static void main(String[] args) {
//        String path = "D:\\dirA";
//        List<File> allFile = getAllFile(path);
//        for (int i = 0; i < allFile.size(); i++) {
//            System.out.println(allFile.get(i));
//        }



    }
}
